home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Disc to the Future 2
/
Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin
/
MAC
/
THINKC
/
4_0
/
UUPC3
/
MAC_SPEC
/
UNIX_LIB
/
SIO.C
< prev
next >
Wrap
Text File
|
1992-02-10
|
11KB
|
606 lines
/* sio.c
Serial I/O for rz/sz
Copyright (c) 1986 Stuart Lynne
June 1986
Modified for Think C
Sak Wathanasin 1989
Portions Copyright ⌐ David Platt, 1992, 1991. All Rights Reserved
Worldwide.
*/
#include "sio.h"
#include <stdio.h>
#ifndef THINK_C
#include <pb.h>
#include <osutil.h>
/* #include <max/macglobals.h> */
#include <max/debug.h>
#include <max/asc.h>
#else THINK_C
# include "dcp.h"
#endif THINK_C
#ifndef FALSE
# define FALSE 0
#endif FALSE
#ifndef TRUE
# define TRUE 1
#endif TRUE
#ifdef Upgrade
static int g_setting;
#endif Upgrade
struct SIOPort curPort={0};
#ifdef DOASYNC
static struct async_write *asyncout;
static int async_head, async_tail, async_pending;
static int allowInterrupts = FALSE;
static int interruptOccurred = FALSE;
static int sleepLimit = 3;
#endif
#define baud38400 1
struct {
unsigned int baudr;
int speedcode;
} speeds[] = {
300, baud300,
600, baud600,
1200, baud1200,
2400, baud2400,
4800, baud4800,
9600, baud9600,
19200, baud19200,
38400, baud38400,
57600, baud57600,
0,
};
static char otherIn[] = "\p.?In";
static char otherOut[] = "\p.?Out";
static unsigned int
getspeed(code)
{
register n;
for (n=0; speeds[n].baudr; ++n)
if (speeds[n].speedcode == code)
return speeds[n].baudr;
return -1;
}
static unsigned
getbaud(code)
char *code; {
register n;
register long int Baudrate;
Baudrate = atol(code);
for(n=0 ; speeds[n].baudr ; ++n)
if(speeds[n].baudr == Baudrate)
return(speeds[n].speedcode);
return -1;
}
SIOInit ( whichport, speed )
char * whichport;
char * speed;
{
char i;
SerShk handshake;
int setting, baudCode, speedVal;
int err;
long int bytes;
/* fprintf( stderr, "sioinit %s %s\n", whichport, speed ); /* */
if (
strncmp( whichport, ".a", 2 ) == 0 ||
strncmp( whichport, "a",1 ) == 0 ||
strcmp( whichport, "modem") == 0
)
{
curPort.in = AIN;
curPort.out = AOUT;
}
else if (
strncmp( whichport, ".b", 2 ) == 0 ||
strncmp( whichport, "b", 1 ) == 0 ||
strcmp( whichport, "printer") == 0
)
{
curPort.in = BIN;
curPort.out = BOUT;
}
else if (strlen(whichport) == 1 && whichport[0] >= 'c' && whichport[0] <= 'z') {
otherIn[2] = otherOut[2] = whichport[0];
curPort.in = otherIn;
curPort.out = otherOut;
} else if (strlen(whichport) == 2 && whichport[0] == '.' && whichport[1] >= 'c' && whichport[1] <= 'z') {
otherIn[2] = otherOut[2] = whichport[1];
curPort.in = otherIn;
curPort.out = otherOut;
} else
return( -1 );
baudCode = getbaud(speed);
if (baudCode == -1) {
fprintf(stderr, "Baud rate %s is not supported or not recognized\n", speed);
return (-1);
}
speedVal = getspeed(baudCode);
if (speedVal <= 9600) {
sleepLimit = 3;
} else if (speedVal < 57600) {
sleepLimit = 1;
} else {
sleepLimit = 0;
}
if ((err = OpenDriver ( (StringPtr)curPort.in, &curPort.refin )) !=0 ) {
fprintf( stderr, "Err: %d\n", err);
#ifdef DEBUG
debugMsg ( ctop( curPort.in ) );
#endif
SysBeep (20);
return( -1 );
}
if ((err=OpenDriver ( (StringPtr)curPort.out, &curPort.refout )) !=0 ) {
fprintf( stderr, "Err: %d\n", err);
#ifdef DEBUG
debugMsg ( ctop( curPort.out ) );
#endif
SysBeep (20);
return( -1 );
}
SIOHandshake( FALSE, FALSE, FALSE, XON, XOFF );
SIOSetting( speed, noParity, stop10, data8 );
#ifdef DOASYNC
bytes = BUFFERS * sizeof (struct async_write);
asyncout = (struct async_write *) NewPtr(bytes);
if (asyncout) {
memset(asyncout, 0, bytes);
}
async_head = async_tail = 0;
allowInterrupts = interruptOccurred = FALSE;
#endif
return( 0 );
}
SIOSpeed( speed )
char * speed;
{
SIOSetting( speed, curPort.parity, curPort.stopbits, curPort.databits );
}
SIOHandshake ( fInx, fXOn, fCTS, xOn, xOff )
{
int err;
curPort.handshake.fInX = fInx;
curPort.handshake.fXOn = fXOn;
curPort.handshake.fCTS = fCTS;
curPort.handshake.xOn = xOn;
curPort.handshake.xOff = xOff;
/* handshake.fXOn = TRUE; */
curPort.handshake.errs = 0;
curPort.handshake.evts = 0;
if ((err=SerHShake (curPort.refin, &curPort.handshake ))!=0 ) {
fprintf( stderr, "Err: %d\n", err);
#ifdef DEBUG
debugMsg ("\PSerHShake error");
#endif
SysBeep (20);
}
}
SIOSetting( speed, parity, stopbits, databits )
char * speed;
{
int err;
int setting;
curPort.baud = getbaud(speed);
curPort.parity = parity;
curPort.stopbits = stopbits;
curPort.databits = databits;
setting = curPort.baud + parity + stopbits + databits;
#ifdef Upgrade
/* store current settings in a global area */
g_setting = setting;
#endif Upgrade
if ((err=SerReset(curPort.refin, setting))!=0 ) {
fprintf( stderr, "Err: %d\n", err);
#ifdef DEBUG
debugMsg ("\PSerReset error");
#endif
SysBeep (20);
}
}
SIOInBuffer ( buf, size )
char * buf;
int size;
{
curPort.inbuffer = buf;
curPort.insize = size;
SerSetBuf( curPort.refin, buf, size );
}
SIOOutBuffer ( buf, size )
char * buf;
int size;
{
curPort.outbuffer = buf;
curPort.outsize = size;
SerSetBuf( curPort.refout, buf, size );
}
SIOClose ( dtr )
{
CntrlParam SIOpb;
long count;
if ( dtr != 0 && curPort.refin != 0) {
/* drop DTR */
SIOpb.ioCompletion = NULL;
SIOpb.ioRefNum = curPort.refin;
SIOpb.csCode = 18;
PBControl ((ParmBlkPtr)&SIOpb, FALSE);
}
SIOInBuffer( NULL, 0 );
SIOOutBuffer( NULL, 0 );
if (curPort.refin != 0) CloseDriver( curPort.refin );
if (curPort.refout != 0)CloseDriver( curPort.refout );
if (asyncout) {
DisposPtr(asyncout);
asyncout = NULL;
}
async_head = async_tail = async_pending = 0;
curPort.refin = curPort.refout = 0;
}
sfflushout ()
{
}
SIOSetFlowCtl(flag)
int flag;
{
SerShk flowRec;
flowRec.fXOn = flag;
flowRec.fInX = flag;
flowRec.fCTS = 0; /* bad juju to try... input handshake might be DTR */
flowRec.xOn = 0x11;
flowRec.xOff = 0x13;
flowRec.errs = flowRec.evts = 0;
SerHShake(curPort.refin, &flowRec);
SerHShake(curPort.refout, &flowRec);
}
SIOAllowInterrupts(flag)
int flag;
{
int oldFlag;
oldFlag = allowInterrupts;
allowInterrupts = flag;
interruptOccurred &= flag;
return oldFlag;
}
SIOInterrupt()
{
interruptOccurred = TRUE;
}
SIOPurge ()
{ /*
char ch;
while (sread (&ch, 1, 1) == 1);
*/
(void) KillIO(curPort.refin);
(void) KillIO(curPort.refout);
}
SIOPutchar ( ch )
char ch;
{
/*fprintf(stderr, "<%02x>", ch);*/
return( putu ( &ch, 1, curPort.refout ) );
}
SIOWrite ( buf, count )
char * buf;
int count;
{
return( putu (buf, count, curPort.refout) );
}
int SIOAvail()
{
long int count;
(void)SerGetBuf(curPort.refin, &count);
return count;
}
SIOWStr ( st )
char * st;
{
return( putu (st, strlen(st), curPort.refout) );
}
#define Ticks (*(long *) 0x16a)
/* timeout is in tenths of a second */
int SIORead ( byt, mincount, maxcount, tenths )
char * byt;
int mincount;
int maxcount;
long int tenths;
{
long timea;
short actCount;
int i;
timea = Ticks;
tenths *= 6;
/* fprintf (stderr, "Read m= %d T= %ld", maxcount, Ticks );/**/
do {
actCount = getn (byt, mincount, maxcount, curPort.refin );
if (actCount > 0) {
/* fprintf (stderr, " OK: %d\n", actCount);/**/
return actCount;
}
if (allowInterrupts && interruptOccurred) {
return -1;
}
} while ((long)(Ticks - timea) < tenths);
/* fprintf (stderr, " Timed out: t= %d\n T:%ld", tenths, Ticks );/**/
return -1;
}
srdchk ()
{
long count;
(void)SerGetBuf(curPort.refin, &count);
if (count >= 1)
return TRUE;
else
return FALSE;
}
#ifdef BREAK
ssendbrk(bnulls) {
int setting;
# ifdef Upgrade
setting = baud300 + noParity + stop10 + data8;
# else Upgrade
setting = curPort.baud + noParity + stop10 + data8;
# endif Upgrade
if(SerReset(curPort.refin, setting)) {
# ifdef DEBUG
debugMsg("\PSerReset error");
# endif
SysBeep(20);
}
swrite("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", bnulls*2);
# ifdef Upgrade
setting = g_setting;
# else Upgrade
setting = curPort.baud + noParity + stop10 + data8;
# endif Upgrade
if(SerReset(curPort.refin, setting)) {
# ifdef DEBUG
debugMsg("\PSerReset error");
# endif
SysBeep(20);
}
return;
}
#endif BREAK
/* Fill array *cp with characters from serial buffer, starting
at 0, until cmax. Return actual chars read. Don't read unless
at least cmin are available.
*/
int getn ( cp, cmin, cmax, refin )
char *cp;
register int cmax, cmin;
register short refin;
{
ParamBlockRec SIOpb;
register ParmBlkPtr pbp = &SIOpb;
long count;
int firstTry = TRUE;
/* fprintf( stderr, " %d", cmin ); /* */
tryit:
(void)SerGetBuf(refin, &count);
SIOpb.ioParam.ioReqCount = count;
if ( count >= cmin) {
if ( count > cmax)
SIOpb.ioParam.ioReqCount = (long) cmax;
printmsg(4, "Read %ld", SIOpb.ioParam.ioReqCount);
SIOpb.ioParam.ioRefNum = refin;
SIOpb.ioParam.ioBuffer = (Ptr) cp;
SIOpb.ioParam.ioPosMode = 0;
PBRead (&SIOpb, FALSE);
count = SIOpb.ioParam.ioActCount;
#ifdef MULTIFINDER
if (Ticks-Last_Check_Event >= MF_DELAY)
if (Check_Events(0)) {
if (Main_State == Abort_Program) {
SIOClose(TRUE);
exit(-1);
}
}
#endif
}
else {
#ifdef MULTIFINDER
/* the data hasn't been received, ok to delay a bit */
if (Ticks-Last_Check_Event >= MF_DELAY)
if (Check_Events(sleepLimit)) {
if (Main_State == Abort_Program) {
SIOClose(TRUE);
exit(-1);
}
}
#endif
count = 0;
if (firstTry) {
firstTry = FALSE;
goto tryit;
}
}
return( (int)count );
}
static ParamBlockRec pb = {0};
int SIOWriteBusy()
{
if (pb.ioParam.ioResult == 1) {
return TRUE;
} else {
return FALSE;
}
}
int putu( c, count, refout )
char *c;
short count;
short refout;
{
register ParmBlkPtr pbp = &pb;
int spin;
int isAsync;
#ifdef DOASYNC
isAsync = (asyncout != NULL) && (count <= BUFSIZE);
if (isAsync) {
spin = TRUE;
do {
if (async_pending == 0) {
spin = FALSE;
} else {
pbp = &asyncout[async_tail].pb;
if (pbp->ioParam.ioResult != 1) {
async_pending --;
async_tail = (async_tail + 1) % BUFFERS;
} else {
#ifdef MULTIFINDER
if (Ticks-Last_Check_Event >= MF_DELAY)
if (Check_Events(0))
if (Main_State == Abort_Program) {
SIOClose(TRUE);
exit(-1);
}
#endif
if (async_pending < BUFFERS) {
spin = FALSE;
}
}
}
} while (spin);
pbp = &asyncout[async_head].pb;
memcpy(asyncout[async_head].buf, c, (long) count);
pbp->ioParam.ioCompletion = NULL;
pbp->ioParam.ioRefNum = refout;
pbp->ioParam.ioBuffer = asyncout[async_head].buf;
pbp->ioParam.ioReqCount = count;
pbp->ioParam.ioPosMode = 0;
PBWrite(pbp, TRUE);
async_head = (async_head + 1) % BUFFERS;
async_pending ++;
} else {
#endif
pb.ioParam.ioCompletion = NULL;
pb.ioParam.ioRefNum = refout;
pb.ioParam.ioBuffer = c;
pb.ioParam.ioReqCount = count;
pb.ioParam.ioPosMode = 0;
PBWrite(&pb, FALSE );
#ifdef DOASYNC
}
#endif
#ifdef MULTIFINDER
if (Ticks-Last_Check_Event >= MF_DELAY)
if (Check_Events(0))
if (Main_State == Abort_Program) {
SIOClose(TRUE);
exit(-1);
}
#endif
return( (short) pb.ioParam.ioActCount );
}